<template>
  <div class="remote-select-wrapper">
    <a-select
      v-model="selectedValue"
      :allow-clear="allowClear"
      :loading="fetching"
      :trigger-props="{ updateAtScroll }"
      placeholder="请选择"
      allow-search
      v-bind="$attrs"
      popup-container=".remote-select-wrapper"
      @change="handleChangeFn"
      @blur="handleBlurFn"
      @focus="handleFocusFn"
    >
      <template #label="{ data }">
        <slot name="label" :data="data">
          {{ selector.labelFn ? selector.labelFn(selectedOption) : data.label }}
        </slot>
      </template>
      <a-option
        v-for="(item, optionIndex) in options"
        :key="item[selector.key]"
        :value="item[selector.key].toString()"
        :disabled="item.disabled"
      >
        <slot name="option" :option="item" :index="optionIndex">
          {{ selector.optionFn ? selector.optionFn(item) : item[selector.label] }}
        </slot>
      </a-option>
    </a-select>
  </div>
</template>

<script setup name="RemoteOnceSelect">
  import { ref, computed, onMounted, readonly, watch } from 'vue'

  const props = defineProps({
    modelValue: [Number, String],
    type: {
      type: String,
      default: 'default',
    },
    selector: Object,
    valueLabel: String,
    params: {
      type: Object,
      default: () => {},
    },
    allowClear: {
      type: Boolean,
      default: () => true,
    },
    // 滚动容易导致下拉菜单分离
    updateAtScroll: {
      type: Boolean,
      default: () => false,
    },
    // 滚动关闭下拉菜单
    scrollToClose: {
      type: Boolean,
      default: () => false,
    },
  })
  const emit = defineEmits(['focus', 'blur', 'update:modelValue', 'change'])
  defineExpose({ props })

  // 初始化页面参数
  const selector = readonly(props.selector)
  const list = ref([])
  const fetching = ref(false)

  // 当前选中的选项
  const selectedOption = computed(() => {
    if (list.value && list.value.length) {
      const current = list.value.find((item) => item[selector.key || 'id'] == props.modelValue)
      return current || {}
    } else {
      return {}
    }
  })

  // 初始化当前值可能作废的数据，并禁用 before
  const disabledItem = {
    disabled: true,
  }
  watch(
    () => props.valueLabel,
    () => {
      disabledItem[selector.key] = props.modelValue
      disabledItem[selector.label] = props.valueLabel || '-'
    },
    { immediate: true }
  )
  // 初始化不作废的数据end

  // 下拉数据 before
  const options = computed(() => {
    if (disabledItem[selector.key] == null) return list.value
    // == disabledItem[selector.key]
    const current = list.value.find((item) => item[selector.key] == props.modelValue)
    if (current) return list.value
    // value不存在list中，插入不可选择item
    return [disabledItem, ...list.value]
  })
  // 下拉数据 end

  // 选择器的值
  const selectedValue = computed(() => {
    if (props.modelValue == undefined) return undefined
    return props.modelValue.toString()
  })

  // change 事件
  const handleChangeFn = (value) => {
    const option = options.value.find((item) => item[selector.key] == value) || {}
    emit('update:modelValue', value)
    emit('change', value, option)
  }
  // 获取焦点
  const handleFocusFn = () => {
    emit('focus')
  }
  // 失去焦点
  const handleBlurFn = () => {
    emit('blur')
  }

  // 接口方法
  const fetchListApi = async (value) => {
    fetching.value = true
    const queryParam = {
      ...selector.data, // 固定参数
      ...props.params,
    }
    // 参数增加关键字
    queryParam[selector.keyword] = value
    // fetch
    const res = await selector.api(queryParam)
    fetching.value = false
    if (res.code == 200) {
      const result = res.result || [] // 可能为null
      // 兼容
      if (result.data) {
        list.value = result.data
      } else {
        list.value = result
      }
    }
  }
  // 初始化调用列表
  onMounted(() => {
    // TODO catch接口返回值到selector
    fetchListApi()
  })
</script>

<style lang="less" scoped>
  .remote-select-wrapper {
    width: 100%;
    position: relative;
  }
</style>
